#ifndef BLOCKING_QUEUE_H
#define BLOCKING_QUEUE_H

/**
 * @file blocking_queue.h
 * @brief 提供线程安全的阻塞队列模板，用于跨线程传递数据。
 *
 * 队列支持多生产者、多消费者模型，内部使用 mutex 和条件变量实现。
 * 当 Stop() 被调用后，正在等待的 Pop() 会被唤醒并返回 std::nullopt。
 */

#include <condition_variable>
#include <mutex>
#include <optional>
#include <queue>

/**
 * @class BlockingQueue
 * @brief 模板类，提供阻塞式入队/出队能力。
 *
 * @tparam T 队列中存储的元素类型，需支持 move 语义。
 */
template <class T>
class BlockingQueue {
public:
    /**
     * @brief 向队列推入一个元素。
     * 
     * @param value 要推入的元素，可移动。
     */
    void Push(T value) {
        {
            std::lock_guard lock(mutex_);
            queue_.push(std::move(value));
        }
        // 唤醒一个等待中的 Pop() 调用。
        cv_.notify_one();
    }

    /**
     * @brief 阻塞直到取出一个元素或队列停止。
     *
     * @return 取出的元素；当 Stop() 已调用且队列为空时返回 std::nullopt。
     */
    std::optional<T> Pop() {
        std::unique_lock lock(mutex_);
        // 当队列为空时等待，但若 stop_ 为真则直接退出。
        cv_.wait(lock, [&] { return stop_ || !queue_.empty(); });

        if (queue_.empty()) {
            return std::nullopt;  // 队列已停止且为空。
        }

        T value = std::move(queue_.front());
        queue_.pop();
        return value;
    }

    /**
     * @brief 停止队列，唤醒所有等待线程。
     *
     * 调用后，所有 Pop() 将返回 std::nullopt，Push() 不再影响等待线程。
     */
    void Stop() {
        {
            std::lock_guard lock(mutex_);
            stop_ = true;
        }
        cv_.notify_all();
    }

private:
    std::mutex mutex_;                    ///< 保护队列的互斥锁。
    std::condition_variable cv_;          ///< 条件变量，用于阻塞/唤醒消费者。
    std::queue<T> queue_;                 ///< 实际存储元素的队列。
    bool stop_ = false;                   ///< 标记队列是否停止。
};

#endif  // BLOCKING_QUEUE_H